<template>
  <div class="gs-index-list">
    <div id="index-list-content" class="index-list-content">
      <scroll
        ref="indexList">
        <ul>
          <li ref="listGroup" v-for="group in list" :key="group.name">
            <h2 class="index-list-anchor">{{group.name}}</h2>
            <ul>
              <li
                class="index-list-item"
                v-for="item in group.items"
                :key="item.name"
              >{{item.name}}</li>
            </ul>
          </li>
        </ul>
      </scroll>
    </div>
    <div class="index-list-nav">
      <ul>
        <li
          v-for="(item,index) in shortCutList"
          :key="index"
          :class="{'active': currentIndex === index}"
          :data-index="index"
          @touchstart="onShortCutTouchStart"
          @touchmove.stop.prevent="onShortCutTouchMove"
        >{{item}}</li>
      </ul>
    </div>
    <div ref="indexFixed" class="index-list-fixed" v-show="fixedTitle">
      <h2 class="index-list-anchor">{{fixedTitle}}</h2>
    </div>
  </div>
</template>

<script type="text/ecmascript-6">
import Scroll from 'example/components/scroll/scroll'
import { getData } from 'example/common/js/dom'

const TITAL_HEIGHT = 0
const SUB_TITLE_HEIGHT = 40
const ANCHOR_HEIGHT = 22

export default {
  name: 'GsIndexList',
  data () {
    return {
      // 当前滚动位置索引
      currentIndex: 0,
      // 当前滚动的距离
      scrollY: -1,
      // indexFixed移动的距离
      diff: -1
    }
  },
  props: {
    list: {
      type: Array,
      default: () => []
    }
  },
  computed: {
    // indexFixed标题
    fixedTitle () {
      if (this.scrollY >= -TITAL_HEIGHT) {
        return ''
      }
      return this.list[this.currentIndex] ? this.list[this.currentIndex].name : ''
    },
    shortCutList () {
      return this.list.map((group) => {
        return group.name.substr(0, 1)
      })
    }
  },
  components: {
    Scroll
  },
  created () {
    this.touch = {}
  },
  mounted () {
    this._calculateHeight()
    this.$refs.indexList.scroll.on('scroll', pos => {
      this.scrollY = pos.y
    })
    this.$refs.indexList.scroll.on('scrollEnd', pos => {
      this.scrollY = pos.y
    })
  },
  watch: {
    diff (newVal) {
      let fixedTop = (newVal > 0 && newVal < SUB_TITLE_HEIGHT) ? newVal - SUB_TITLE_HEIGHT : 0
      if (this.fixedTop === fixedTop) {
        return
      }
      this.fixedTop = fixedTop
      this.$refs.indexFixed.style.transform = `translate3d(0, ${fixedTop}px, 0)`
    },
    scrollY (newVal) {
      let newY = newVal
      let listHeight = this.listHeight

      // 当滚动到顶部，newY>0
      if (newY > -TITAL_HEIGHT) {
        this.currentIndex = 0
        return
      }

      for (let i = 0; i < listHeight.length - 1; i++) {
        let height1 = listHeight[i]
        let height2 = listHeight[i + 1]
        if (-newY >= height1 && -newY < height2) {
          this.currentIndex = i
          this.diff = height2 + newY
          return
        }
      }

      // 当滚动到底部，且-newY大于最后一个元素的上限
      this.currentIndex = this.listHeight.length - 2
    }
  },
  methods: {
    refresh () {
      this.$refs.indexList.refresh()
    },
    onShortCutTouchStart (e) {
      let anchorIndex = getData(e.currentTarget, 'index')
      let firstTouch = e.touches[0]
      this.touch.y1 = firstTouch.pageY
      this.touch.anchorIndex = anchorIndex

      this._scrollTo(anchorIndex)
    },
    onShortCutTouchMove (e) {
      let firstTouch = e.touches[0]
      this.touch.y2 = firstTouch.pageY
      let delta = (this.touch.y2 - this.touch.y1) / ANCHOR_HEIGHT | 0
      let anchorIndex = parseInt(this.touch.anchorIndex) + delta

      this._scrollTo(anchorIndex)
    },
    _calculateHeight () {
      let list = this.$refs.listGroup
      let height = TITAL_HEIGHT
      if (!list) {
        return
      }
      this.listHeight = []
      this.listHeight.push(height)
      Array.prototype.slice.call(list).forEach((group) => {
        height += group.clientHeight
        this.listHeight.push(height)
      })
    },
    _scrollTo (index) {
      if (!index && index !== 0) {
        return
      }
      if (index < 0) {
        index = 0
      } else if (index > this.listHeight.length - 2) {
        index = this.listHeight.length - 2
      }

      this.$refs.indexList.scroll.scrollToElement(this.$refs.listGroup[index], 100)
      this.scrollY = this.$refs.indexList.scroll.y
    }
  }
}
</script>

<style lang="scss">
.gs-index-list {
  position: relative;
  width: 100vw;
  height: calc(100vh - 45px);
  font-size: 14px;
  overflow: hidden;
  .pullDown-wrapper {
    position: absolute;
    top: 0;
    width: 100%;
    .pullDown-text {
      width: 100%;
      padding-top: 10px;
      text-align: center;
      color: rgba(0, 0, 0, 0.6);
    }
  }
  .pullUp-wrapper {
    width: 100%;
    padding: 5px 0 15px;
    .pullUp-text {
      width: 100%;
      padding-top: 10px;
      text-align: center;
      color: rgba(0, 0, 0, 0.6);
    }
  }
  .index-list-nav {
    position: absolute;
    right: 3px;
    top: 35vh;
    z-index: 1;
    ul {
      li {
        padding: 0 8px 8px 0;
        line-height: 1;
        text-align: center;
        user-select: none;
        &.active {
          color: #409eff;
        }
      }
    }
  }
  .index-list-fixed {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    z-index: 1;
    .index-list-anchor {
      padding: 16px 16px 10px 16px;
      font-size: 14px;
      color: #999;
      background: #f7f7f7;
    }
  }
  .index-list-content {
    position: relative;
    height: 100%;
    background: transparent;
    z-index: 1;
    ul {
      background: white;
    }
    .index-list-title {
      padding: 14px 16px;
      font-size: 12px;
      line-height: 1.6;
      color: grey;
    }
    .index-list-anchor {
      padding: 16px 16px 10px 16px;
      font-size: 14px;
      color: #999;
      background: #f7f7f7;
    }
    .index-list-item {
      position: relative;
      height: 50px;
      line-height: 50px;
      padding: 0 16px;
      font-size: 12px;
      color: grey;
      &:last-child {
        border: none;
      }
    }
    .index-list-item_active {
      background: grey;
    }
  }
}
</style>
